﻿using huqiang.Core.HGUI;
using huqiang.Data;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using UnityEditor;
using UnityEngine;

[InitializeOnLoad]
public class HCanvasEditorUpdate
{
    [UnityEditor.Callbacks.DidReloadScripts(0)]
    static void OnScriptReload()
    {
#if UNITY_2019_1_OR_NEWER
        SceneView.beforeSceneGui -= DuringSceneGui;
        SceneView.beforeSceneGui += DuringSceneGui;
#else
        SceneView.onSceneGUIDelegate -= DuringSceneGui;
        SceneView.onSceneGUIDelegate += DuringSceneGui;
#endif
    }
    static void DuringSceneGui(SceneView view)
    {
        OnSceneGUI();
    }
    public enum PlayModeState
    {
        Playing,
        Paused,
        Stop,
        PlayingOrWillChangePlayMode
    }
    class DataContext
    {
        public string guid;
        public UIElement Root;
    }
    static HCanvasEditorUpdate()
    {
        OnScriptReload();
        EditorApplication.update += Update;
        EditorApplication.hierarchyChanged += OnHierarchyChanged;
        if(EditorApplication.isCompiling)
            UIElement.DisposeAll();
    }
    static float time;
    static Transform LastSelect;
    static void Update()
    {
        if (Application.isPlaying)
            return;
        if (EditorApplication.isCompiling)
        { 
            UIElement.DisposeAll();
        }
        var renders = SceneAsset.FindObjectsOfType(typeof(HGUIRender));
        if (renders != null)
        {
            for (int i = 0; i < renders.Length; i++)
            {
                var obj = renders[i] as HGUIRender;
                if (obj != null)
                {
                    obj.Refresh();
                }
            }
        }
        time += Time.deltaTime;
        if(time>1)
        {
            time = 0;
            //var sys = SceneAsset.FindObjectsOfType(typeof(UISystem));
            //if (sys != null)
            //{
            //    if (sys.Length > 0)
            //        (sys[0] as UISystem).OverCamera();
            //}
            var objs = SceneAsset.FindObjectsOfType(typeof(UIHelper));
            if (objs != null)
            {
                for (int i = 0; i < objs.Length; i++)
                {
                    var obj = objs[i] as UIHelper;
                    if (obj != null)
                        obj.Refresh();
                }
            }
            if (renders != null)
                for (int i = 0; i < renders.Length; i++)
                {
                    var obj = renders[i] as HGUIRender;
                    UIAdaptive.ResizeChild(obj.canvas);
                    MakeContext(obj);
                }
        }
    }
    static void MakeContext(HGUIRender render)
    {
        var trans = render.transform;
        var c = trans.childCount;
        if (render.canvas == null)
            return;
        var p = render.canvas;
 
        //trans.localPosition = p.localPosition;
        //trans.localRotation = p.localRotation;
        //trans.localScale = p.localScale;
        p.name = trans.name;
        p.activeSelf =render.gameObject.activeSelf;
        for (int i = 0; i < c; i++)
        {
            var son = trans.GetChild(i);
            var uc = son.GetComponent<huqiang.Helper.HGUI.UIContext>();
            if (uc != null)
            {
                var ud = uc.GetUIData();
                if (ud != null)
                {
                    ud.Context = son;
                    ud.SetParent(p);
                    uc.MakeContext();
                }
            }
        }
    }
    static void MakeContext(UIElement element)
    {
        if(element.Context!=null)
        {
            element.Context.localPosition = element.localPosition;
            element.Context.localRotation = element.localRotation;
            element.Context.localScale = element.localScale;
        }
        var c = element.child.Count;
        for (int i = 0; i < c; i++)
            MakeContext(element.child[i]);
    }
    static void OnHierarchyChanged()
    {
        if (!Application.isPlaying)
            UIElement.DisposeAll();
    }
    static List<DataContext> CanvasCash = new List<DataContext>();
    public static HCanvas GetData(HGUIRender render)
    {
        string guid = render.GetGuid();
        for(int i=0;i<CanvasCash.Count;i++)
        {
            if(guid==CanvasCash[i].guid)
            {
                return CanvasCash[i].Root as HCanvas;
            }
        }
        string dic = Environment.CurrentDirectory + "/hgui2";
        string path = dic + "/" + render.GetGuid() + ".bytes";
        if (File.Exists(path))
        {
            byte[] dat = File.ReadAllBytes(path);
            huqiang.Core.HGUI.UIElement.DisposeAll();
            if (HGUIManager.GameBuffer == null)
                HGUIManager.Initial();
            if (render.canvas == null)
                render.canvas = new HCanvas();
            CloneAll(new DataBuffer(dat), render.canvas);
            DataContext dc = new DataContext();
            dc.guid = guid;
            dc.Root = render.canvas;
            CanvasCash.Add(dc);
            return render.canvas;
        }
        return null;
    }
    static void CloneAll(DataBuffer db, UIElement root)
    {
        root.child.Clear();
        var fake = HGUIManager.LoadModels(db, "assTest").models;
        var child = HGUIManager.GetAllChild(fake);
        if (child != null)
        {
            for (int i = 0; i < child.Length; i++)
            {
                var go = HGUIManager.Clone(child[i]);
                if (go != null)
                {
                    go.SetParent(root);
                    go.localScale = Vector3.one;
                }
            }
        }
    }

    static void OnSceneGUI()
    {
        if (UnityEngine.Event.current != null)
        {
            if (Event.current.type == EventType.MouseUp)
            {
                if (UnityEngine.Event.current.button == 0)
                {
                    var pos = UnityEngine.Event.current.mousePosition;
                    var win = EditorWindow.mouseOverWindow as SceneView;
                    if (win == null)
                        return;
                    var renders = SceneAsset.FindObjectsOfType(typeof(HGUIRender));
                    if (renders != null)
                    {
                        var ray = HandleUtility.GUIPointToWorldRay(pos);
                        for (int i = 0; i < renders.Length; i++)
                        {
                            var render = renders[i] as HGUIRender;
                            Vector2 cast = Vector2.zero;
                            if(ScreenToCanvasPos2(render.transform, ray,ref cast))
                            {
                                LastSelect = Ray(render, LastSelect, cast);
                                if (LastSelect != null)
                                {
                                    Selection.activeTransform = LastSelect;
                                    UnityEngine.Event.current.Use();
                                }
                            }
                        }
                    }
                }
            }
        }

        if (Application.isPlaying)
        {
            DrawBorder(UIHierarchy.SelectNode);
        }
    }
    public static void DrawBorder(UIElement ui)
    {
        if (ui == null)
            return;
        Handles.color = Color.red;
        Vector3[] verts = new Vector3[8];
        var root = ui.root;
        float s = 1;
        var r = (root as HCanvas).render;
        if (r != null)
        {
            s = r.renderScale.x;
            var info = UIAdaptive.GetGlobaInfo(ui);
            var pos = r.transform.position;
            var op = info.Position - pos;
            var p = pos + op * s;
            //var p = txt.transform.position;
            var size = ui.SizeDelta;
            size.x *= info.Scale.x * s;
            size.y *= info.Scale.y * s;
            var bor = new Border(size, ui.Pivot);
            var q = info.Rotation;
            var lt = p + q * new Vector3(bor.left, bor.top, 0);
            var rt = p + q * new Vector3(bor.right, bor.top, 0);
            var rd = p + q * new Vector3(bor.right, bor.down, 0);
            var ld = p + q * new Vector3(bor.left, bor.down, 0);
            verts[0] = lt;
            verts[1] = rt;
            verts[2] = rt;
            verts[3] = rd;
            verts[4] = rd;
            verts[5] = ld;
            verts[6] = ld;
            verts[7] = lt;
            Handles.DrawLines(verts);
        }
    }

    static bool ScreenToCanvasPos2(Transform trans, Ray ray,ref Vector2 cast)
    {
        Vector3 a = new Vector3(-10000f, -10000f, 0);
        Vector3 b = new Vector3(0, 10000f, 0);
        Vector3 c = new Vector3(10000, -10000, 0);
        var pos = trans.position;
        var qt = trans.rotation;
        a = qt * a + pos;
        b = qt * b + pos;
        c = qt * c + pos;//得到世界坐标的三角面
        var v = ray.origin;//cam.ScreenToWorldPoint(mPos);
        var f = ray.direction;//cam.transform.forward;
        Vector3 p = Vector3.zero;
        if (huqiang.Physics.IntersectTriangle(ref v, ref f, ref a, ref b, ref c, ref p))
        {
            cast = new Vector2(p.x, p.y);
            return true;
        }
        return false;
    }
    static Transform Ray(HGUIRender root, Transform last,Vector2 mouse)
    {
        List<Transform> tmp = new List<Transform>();
        var c = root.trans.childCount-1;
        RayChild(root.trans, tmp, mouse);
        if (tmp.Count == 0)
            return null;
        if (last == null)
            return tmp[0];
        int index = tmp.IndexOf(last);
        index++;
        if (index >= tmp.Count)
            index = 0;
        return tmp[index];
    }
    static void RayChild(Transform trans,List<Transform> tmp,Vector2 mouse)
    {
        var c = trans.childCount - 1;
        for (; c >= 0; c--)
        {
            var son = trans.GetChild(c);
            if (son.gameObject.activeSelf)
            {
                RayChild(son, tmp, mouse);
                var context = son.GetComponent<huqiang.Helper.HGUI.UIContext>();
                if (context != null)
                {
                    var hg = context.GetUIData() as HGraphics;
                    if (hg != null)
                    {
                        if (RayCastHGraphics(son, hg, mouse))
                        {
                            tmp.Add(son);
                        }
                    }
                }
            }
        }
    }
    static Vector2[] v4 = new Vector2[4];
    static bool RayCastHGraphics(Transform trans, HGraphics ui, Vector2 mouse)
    {
        var matrix = trans.localToWorldMatrix;
        var size = ui.SizeDelta;
        var bor = new Border(size, ui.Pivot);
        var lt = matrix.MultiplyPoint(new Vector3(bor.left, bor.top, 0));
        var rt = matrix.MultiplyPoint(new Vector3(bor.right, bor.top, 0));
        var rd = matrix.MultiplyPoint(new Vector3(bor.right, bor.down, 0));
        var ld = matrix.MultiplyPoint(new Vector3(bor.left, bor.down, 0));
        v4[0] = lt;
        v4[1] = rt;
        v4[2] = rd;
        v4[3] = ld;
        return huqiang.Physics2D.DotToPolygon(v4, mouse);
    }
}